from django.http import HttpResponse
from django.shortcuts import render
from urllib.parse import parse_qsl
import json
import urllib.parse as up
import datetime
import time


def check_is_api(request):
    """
    检测是否是api来的流量
    :param request:
    :return:
    """
    full_path = request.get_full_path_info()
    if full_path.startswith("/api/"):
        return True


def check_param_is_complete(source_param, must_param):
    """
    校验参数是否齐全
    :param source_param:
    :param must_param:
    :return:
    """
    if isinstance(source_param, dict) and isinstance(must_param, list):
        for param in must_param:
            if source_param.get(param) is None:
                return False, "incomplete parameters, {} does not exist".format(
                    param
                )
            return True, None
        return False, "wrong format"


def format_request_body_to_dict(body, content_type="json"):
    """
    统一处理请求 body
    :param body:
    :param content_type:
    :return:
    """
    try:
        if isinstance(body, bytes):
            body = body.decode("utf-8")
        if len(body) < 1:
            return False, "param is none"
        if isinstance(body, str) and len(body) > 0:
            if content_type == "json":
                return True, json.loads(body)
            if content_type == "x-www-form-urlencoded":
                return True, dict(parse_qsl(body))
        return False, "wrong format"
    except Exception as e:
        return False, "json format error, msg {}".format(str(e))


def unite_response(request, local):
    """
    返回值统一处理
    :param request:
    :param local:
    :return:
    """
    if check_is_api(request):
        response = local.get("response")
        if response is None:
            raise ValueError("local缺少response字段")
        if not isinstance(response, str):
            response = json.dumps(response, cls=DateEncoder)
        response_final = HttpResponse(
            response, content_type="application/json"
        )
    else:
        if local.get("response") == {}:
            response_final = render(request, "404.html", local)
        else:
            response_final = render(request, local.get("template"), local)
    return response_final


class DateEncoder(json.JSONEncoder):
    """
    重写 JSONEncoder 中的 default 方法
    """
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime("%Y-%m-%d %H:%M:%S")
        elif isinstance(obj, datetime.date):
            return obj.strftime("%Y-%m-%d")
        else:
            return json.JSONEncoder.default(self, obj)

def url_encode_with_query_string(host, url, **kwargs):
    """
    拼接 url
    :param host:
    :param url:
    :param kwargs:
    :return:
    """
    if len(kwargs) > 0:
        query_string = host + url + up.urlencode(kwargs)
    else:
        query_string = host + url
    query_string = query_string.replace("%27", "%22") # ' 转换为 "
    return query_string


def not_null_check(source, check_data):
    """
    参数不为空校验
    :param source:
    :param check_data:
    :return:
    """
    if not isinstance(source, dict):
        return False
    for check_key in check_data:
        if source.get(check_key) is None:
            return False
    return True


def not_null_check_with_errmsg(source: dict, check_data: list):
    """
    参数不为空校验, 带有错误信息
    :param source:
    :param check_data:
    :return:
    """
    for check_key in check_data:
        if source.get(check_key) is None or source.get(check_key) == "":
            return False, "{} is null".format(check_key)
    return True, None


def strf_time(timestamp):
    """
    将时间戳转换为指定日期格式
    :param timestamp:
    :return:
    """
    if not timestamp:
        timestamp = 0
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(timestamp)))


def json_to_dict(json_data):
    """
    json 转 dict
    :param json_data:
    :return:
    """
    if isinstance(json_data, dict) or isinstance(json_data, list):
        return True, json_data
    if not isinstance(json_data, str):
        return False, "json data must be string"
    try:
        dic_response = json.loads(json_data)
        return True, dic_response
    except Exception as e:
        return False, str(e)

def dict_to_json(dict_data):
    """
    dict 转 json
    :return:
    """
    if isinstance(dict_data, dict) or isinstance(dict_data, list):
        return False, "data must be dict"
    try:
        json_response = json.dumps(dict_data)
        return True, json_response
    except Exception as e:
        return False, str(e)
